#include <iostream>
#include <pthread.h>
#include <thread>
#include <unistd.h>
#include <cstring>
#include <cerrno>

using namespace std;
//如果多线程访问同一个全局变量，并对他进行数据计算，多线程们会互相影响吗？
int tickets = 10000;//在并发访问的时候，导致了数据不一致的问题
void* getTickets(void* args)
{
    (void)args;
    while(true)
    {
        if(tickets > 0)
        {
            usleep(1000);
            printf("%p , %d\n", pthread_self(),tickets);
            tickets--;
        }
        else
        {
            break;
        }
    }
}

int main()
{
    pthread_t t1,t2,t3;
    pthread_create(&t1,nullptr,getTickets,nullptr);
    pthread_create(&t2,nullptr,getTickets,nullptr);
    pthread_create(&t3,nullptr,getTickets,nullptr);

    pthread_join(t1,nullptr);
    pthread_join(t2,nullptr);
    pthread_join(t3,nullptr);


    return 0;
}
// void fun()
// {
//     while(true)
//     {
//         cout << "hello new thread " << endl;
//         sleep(1);
//     }
// }
// int main()
// {
//     std::thread t(fun);
//     std::thread t1(fun);
//     std::thread t2(fun);
//     std::thread t3(fun);
//     std::thread t4(fun);

//     while(true)
//     {
//         cout << "hello main thread" << endl;
//         sleep(1);
//     }
//     t.join();
//     return 0;
// }

// __thread int g_val = 10; // _ _ thread修饰全局变量，带来的结果就是让每一个线程各自拥有一个全局的变量--线性的局部存储   
// void *threadRoutine(void *args)
// {

//     while (true)
//     {
//         g_val++;
//         sleep(1);
//         cout << " new thread g_val:" << g_val << "  address :" << &g_val << endl;
//     }
//     // int count = 0;
//     // while (true)
//     // {
//     //     sleep(1);
//     //     cout << "新进程: " << (char *)args << endl;
//     //     if (count++ == 10)
//     //     {
//     //         break;
//     //     }
//     // }
//     // 3.进程终止 三种方式
//     // pthread_exit((void*)10);//(1).终止进程，并设置退出码
//     return (void *)10; // (2).直接返回退出码  返回给谁？返回给main线程，使用pthread_join拿到退出码
// }
// int main()
// {
//     // 线程谁先运行跟调度器有关
//     // 任何线程一旦异常，可能会导致整个进程都会退出
//     // 线程的输出和返回值问题
//     // 线程异常退出的理解

//     // 线程控制
//     // 1.创建线程
//     // 因为我们目前用的不是系统接口，而是pthread库中的地址
//     pthread_t tid; // 本质是一个地址
//     int *ret = nullptr;
//     pthread_create(&tid, nullptr, threadRoutine, (void *)"thread 1"); // 创建进程参数分别是   线程ID - 属性 - 回调方法 - 回调方法的参数

//     //sleep(5);
//     while (true)
//     {
//         sleep(1);
//         cout << " main thread g_val:" << g_val << "  address :" << &g_val << endl;
//     }
//     // pthread_cancel(tid); // (3).在主线程进行进程终止，退出码默认是-1
//     // cout << "pthread cancel " << tid << endl;
//     //  2.等待进程  线程在创建的时候，也是需要等待进程的，如果主线程不进行等待，那么会引起类似进程的僵尸问题，内存泄漏！
//     int n = pthread_join(tid, (void **)&ret); // 等待进程 参数: 线程ID - void**(要接收的返回值)
//                                               // 默认会阻塞等待进程退出
//     // while (true)
//     // {
//     //     sleep(1);
//     //     // cout << "main thread success"
//     //     //      << "  " << (long long)ret << " " << strerror(n) << endl;
//     // }
//     return 0;
// }